home *** CD-ROM | disk | FTP | other *** search
/ PC Answers 1995 May / PC Answers CD-ROM 7 (Future Publishing) (May 1995).iso / vbits / code / lang / intro / smilectl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-06  |  8.5 KB  |  295 lines

  1. // smilectl.cpp : Implementation of the CSmileCtrl OLE control class.
  2.  
  3. #include "stdafx.h"
  4. #include "smile.h"
  5. #include "smilectl.h"
  6. #include "smileppg.h"
  7.  
  8.  
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char BASED_CODE THIS_FILE[] = __FILE__;
  12. #endif
  13.  
  14.  
  15. IMPLEMENT_DYNCREATE(CSmileCtrl, COleControl)
  16.  
  17.  
  18. /////////////////////////////////////////////////////////////////////////////
  19. // Message map
  20.  
  21. BEGIN_MESSAGE_MAP(CSmileCtrl, COleControl)
  22.     //{{AFX_MSG_MAP(CSmileCtrl)
  23.     ON_WM_LBUTTONDOWN()
  24.     //}}AFX_MSG_MAP
  25.     ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  26. END_MESSAGE_MAP()
  27.  
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // Dispatch map
  31.  
  32. BEGIN_DISPATCH_MAP(CSmileCtrl, COleControl)
  33.     //{{AFX_DISPATCH_MAP(CSmileCtrl)
  34.     DISP_PROPERTY_NOTIFY(CSmileCtrl, "Sad", m_sad, OnSadChanged, VT_BOOL)
  35.     DISP_FUNCTION(CSmileCtrl, "Beep", Beep, VT_EMPTY, VTS_I2)
  36.     DISP_STOCKFUNC_REFRESH()
  37.     DISP_STOCKPROP_BACKCOLOR()
  38.     DISP_STOCKPROP_CAPTION()
  39.     DISP_STOCKPROP_FONT()
  40.     DISP_STOCKPROP_FORECOLOR()
  41.     //}}AFX_DISPATCH_MAP
  42.     DISP_FUNCTION_ID(CSmileCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
  43. END_DISPATCH_MAP()
  44.  
  45.  
  46. /////////////////////////////////////////////////////////////////////////////
  47. // Event map
  48.  
  49. BEGIN_EVENT_MAP(CSmileCtrl, COleControl)
  50.     //{{AFX_EVENT_MAP(CSmileCtrl)
  51.     EVENT_CUSTOM("Outside", FireOutside, VTS_NONE)
  52.     EVENT_CUSTOM("Inside", FireInside, VTS_I2  VTS_I2)
  53.     EVENT_STOCK_CLICK()
  54.     EVENT_STOCK_KEYPRESS()
  55.     //}}AFX_EVENT_MAP
  56. END_EVENT_MAP()
  57.  
  58.  
  59. /////////////////////////////////////////////////////////////////////////////
  60. // Property pages
  61.  
  62. // TODO: Add more property pages as needed.  Remember to increase the count!
  63. BEGIN_PROPPAGEIDS(CSmileCtrl, 3)
  64.     PROPPAGEID(CSmilePropPage::guid)
  65.     PROPPAGEID(CLSID_CColorPropPage)    //Stock Color Property Page
  66.     PROPPAGEID(CLSID_CFontPropPage)        //Stock Font Property Page
  67. END_PROPPAGEIDS(CSmileCtrl)
  68.  
  69.  
  70. /////////////////////////////////////////////////////////////////////////////
  71. // Initialize class factory and guid
  72.  
  73. IMPLEMENT_OLECREATE_EX(CSmileCtrl, "SMILE.SmileCtrl.1",
  74.     0xedec4485, 0xc101, 0x101b, 0xac, 0x9d, 0x0, 0xaa, 0x0, 0x47, 0xd4, 0xfd)
  75.  
  76.  
  77. /////////////////////////////////////////////////////////////////////////////
  78. // Type library ID and version
  79.  
  80. IMPLEMENT_OLETYPELIB(CSmileCtrl, _tlid, _wVerMajor, _wVerMinor)
  81.  
  82.  
  83. /////////////////////////////////////////////////////////////////////////////
  84. // Interface IDs
  85.  
  86. const IID BASED_CODE IID_DSmile =
  87.         { 0xedec4486, 0xc101, 0x101b, { 0xac, 0x9d, 0x0, 0xaa, 0x0, 0x47, 0xd4, 0xfd } };
  88. const IID BASED_CODE IID_DSmileEvents =
  89.         { 0xedec4487, 0xc101, 0x101b, { 0xac, 0x9d, 0x0, 0xaa, 0x0, 0x47, 0xd4, 0xfd } };
  90.  
  91.  
  92. /////////////////////////////////////////////////////////////////////////////
  93. // Control type information
  94.  
  95. static const DWORD BASED_CODE _dwSmileOleMisc =
  96.     OLEMISC_ACTIVATEWHENVISIBLE |
  97.     OLEMISC_SETCLIENTSITEFIRST |
  98.     OLEMISC_INSIDEOUT |
  99.     OLEMISC_CANTLINKINSIDE |
  100.     OLEMISC_RECOMPOSEONRESIZE;
  101.  
  102. IMPLEMENT_OLECTLTYPE(CSmileCtrl, IDS_SMILE, _dwSmileOleMisc)
  103.  
  104.  
  105. /////////////////////////////////////////////////////////////////////////////
  106. // CSmileCtrl::CSmileCtrlFactory::UpdateRegistry -
  107. // Adds or removes system registry entries for CSmileCtrl
  108.  
  109. BOOL CSmileCtrl::CSmileCtrlFactory::UpdateRegistry(BOOL bRegister)
  110. {
  111.     if (bRegister)
  112.         return AfxOleRegisterControlClass(
  113.             AfxGetInstanceHandle(),
  114.             m_clsid,
  115.             m_lpszProgID,
  116.             IDS_SMILE,
  117.             IDB_SMILE,
  118.             FALSE,                      //  Not insertable
  119.             _dwSmileOleMisc,
  120.             _tlid,
  121.             _wVerMajor,
  122.             _wVerMinor);
  123.     else
  124.         return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  125. }
  126.  
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CSmileCtrl::CSmileCtrl - Constructor
  130.  
  131. CSmileCtrl::CSmileCtrl()
  132. {
  133.     SetInitialSize(200, 200);
  134.     InitializeIIDs(&IID_DSmile, &IID_DSmileEvents);
  135. }
  136.  
  137.  
  138. /////////////////////////////////////////////////////////////////////////////
  139. // CSmileCtrl::~CSmileCtrl - Destructor
  140.  
  141. CSmileCtrl::~CSmileCtrl()
  142. {
  143.     // TODO: Cleanup your control's instance data here.
  144. }
  145.  
  146.  
  147. /////////////////////////////////////////////////////////////////////////////
  148. // CSmileCtrl::OnDraw - Drawing function
  149.  
  150. #define X(x) (int)(xLeft + (x)*xScale/100)    // Scaling macros
  151. #define Y(y) (int)(yTop + (y)*yScale/100)    // so scale is 0 - 100
  152. #define CX(x) (int)((x)*xScale/100)
  153. #define CY(y) (int)((y)*yScale/100)
  154.  
  155. void CSmileCtrl::OnDraw(
  156.             CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
  157. {
  158.     long xLeft = rcBounds.left;            // Use with scaling macros
  159.     long yTop = rcBounds.top;    
  160.     long xScale = rcBounds.Width();
  161.     long yScale = rcBounds.Height();    
  162.  
  163.     int iPenWidth = max(CX(5), CY(5)); // Pen width based on control size
  164.     CBrush brushBack;                   // Background brush
  165.     CBrush brushBlack;
  166.     CBrush brushYellow;
  167.     CPen penBlack(PS_SOLID, iPenWidth, RGB(0x00,0x00,0x00));
  168.     CPen penNull(PS_NULL, 0, (COLORREF)0);    // Null pen for drawing filled ellipses
  169.     COLORREF crBack = TranslateColor(GetBackColor());    //Use BackColor
  170.     brushBack.CreateSolidBrush(crBack);                 //Stock Property
  171. //    brushBack.CreateSolidBrush(RGB(0xff,0xff,0xff));    //remove
  172.     brushBlack.CreateSolidBrush(RGB(0x00,0x00,0x00));
  173.     brushYellow.CreateSolidBrush(RGB(0xff,0xff,0x00));
  174.  
  175.     pdc->FillRect(rcBounds, &brushBack);        // Clear background
  176.  
  177.     CPen* pPenSave = pdc->SelectObject(&penBlack);
  178.     CBrush* pBrushSave = pdc->SelectObject(&brushYellow);
  179.     pdc->Ellipse(X(10), Y(15), X(90), Y(95));    // Head
  180.  
  181.     if (m_sad)                                      //Use Sad
  182.     {                                               //Custom Property
  183.         pdc->Arc(X(25), Y(70), X(75), Y(140),        // Frown Mouth
  184.                X(65), Y(75), X(35), Y(75));
  185.         } else {
  186.         pdc->Arc(X(25), Y(10), X(75), Y(80),        // Smile mouth
  187.                X(35), Y(70), X(65), Y(70));
  188.     }
  189.  
  190.  
  191.     pdc->SelectObject(&penNull);                // No draw width
  192.     pdc->SelectObject(&brushBlack);
  193.     pdc->Ellipse(X(35), Y(35), X(43), Y(50));    // Right eye
  194.     pdc->Ellipse(X(57), Y(35), X(65), Y(50));    // Left eye
  195.     pdc->Ellipse(X(46), Y(35), X(54), Y(50));    // Oops!
  196.     
  197.     pdc->SetBkMode(TRANSPARENT);                       //Use ForeColor
  198.     pdc->SetTextColor(TranslateColor(GetForeColor())); //Stock Property
  199.  
  200.     SelectStockFont(pdc);                              //Use Font 
  201.                                                        //Stock Property
  202.  
  203.     pdc->DrawText(InternalGetText(), -1, rcBounds,     //Use Caption 
  204.         DT_SINGLELINE | DT_CENTER | DT_TOP);           //Stock Propery
  205.  
  206.     pdc->SelectObject(pBrushSave);
  207.     pdc->SelectObject(pPenSave);
  208. }
  209.  
  210.  
  211. /////////////////////////////////////////////////////////////////////////////
  212. // CSmileCtrl::DoPropExchange - Persistence support
  213.  
  214. void CSmileCtrl::DoPropExchange(CPropExchange* pPX)
  215. {
  216.     ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  217.     COleControl::DoPropExchange(pPX);
  218.  
  219.     // TODO: Call PX_ functions for each persistent custom property.
  220.     PX_Bool(pPX, _T("Sad"), m_sad, FALSE);    //Init & Persistence
  221.  
  222. }
  223.  
  224.  
  225. /////////////////////////////////////////////////////////////////////////////
  226. // CSmileCtrl::OnResetState - Reset control to default state
  227.  
  228. void CSmileCtrl::OnResetState()
  229. {
  230.     COleControl::OnResetState();  // Resets defaults found in DoPropExchange
  231.  
  232.     // TODO: Reset any other control state here.
  233. }
  234.  
  235.  
  236. /////////////////////////////////////////////////////////////////////////////
  237. // CSmileCtrl::AboutBox - Display an "About" box to the user
  238.  
  239. void CSmileCtrl::AboutBox()
  240. {
  241.     CDialog dlgAbout(IDD_ABOUTBOX_SMILE);
  242.     dlgAbout.DoModal();
  243. }
  244.  
  245.  
  246. /////////////////////////////////////////////////////////////////////////////
  247. // CSmileCtrl message handlers
  248.  
  249. void CSmileCtrl::OnSadChanged() 
  250. {
  251.     InvalidateControl();   //add...
  252. //    SetModifiedFlag();     //remove
  253. }
  254.  
  255. void CSmileCtrl::Beep(short uAlert) 
  256. {
  257.     MessageBeep((UINT)uAlert);
  258.  
  259. }
  260.  
  261. void CSmileCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  262. {
  263.     CRect rcBounds;
  264.     GetClientRect(&rcBounds);
  265.  
  266.     long xLeft = rcBounds.left;    //Required by X() and Y() macros
  267.     long yTop = rcBounds.top;    
  268.     long xScale = rcBounds.Width();
  269.     long yScale = rcBounds.Height();
  270.  
  271.     if (InEllipse(point, X(10), Y(15), X(90), Y(95)))
  272.         FireInside((short)point.x, (short)point.y);
  273.     else
  274.         FireOutside();
  275.     
  276.     COleControl::OnLButtonDown(nFlags, point);
  277. }
  278.  
  279. //Simple Ellipse Hit-Testing
  280. BOOL CSmileCtrl::InEllipse(const CPoint& pt,
  281.     int x1, int y1, int x2, int y2)
  282. {
  283.     // Determine radii                       
  284.     double a = (x2 - x1) / 2;
  285.     double b = (y2 - y1) / 2;
  286.     
  287.     // Determine x, y
  288.     double x = pt.x - (x1 + x2) / 2;
  289.     double y = pt.y - (y1 + y2) / 2;
  290.     
  291.     // Apply ellipse formula
  292.     return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
  293. }
  294.  
  295.